package com.ys.service.storage.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.dto.AddDto;
import com.ys.entity.base.CheckByGrid;
import com.ys.entity.flow.YspModel;
import com.ys.entity.storage.TccStockAllocate;
import com.ys.entity.storage.TccStockAllocateItem;
import com.ys.entity.storage.TccStockControl;
import com.ys.entity.sys.*;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.enume.storage.TccStockSourceEnum;
import com.ys.mapper.storage.StorageMapper;
import com.ys.mapper.storage.TccStockAllocateItemMapper;
import com.ys.mapper.storage.TccStockAllocateMapper;
import com.ys.service.flow.YspTaskService;
import com.ys.service.storage.TccStockAllocateService;
import com.ys.service.storage.TccStockControlService;
import com.ys.util.CheckUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;

/**
 * 库存调拨单
 */
@Service("tccStockAllocateService")
public class TccStockAllocateServiceImpl implements TccStockAllocateService {
	private static final Logger logger = LoggerFactory.getLogger(TccStockAllocateServiceImpl.class);

	@Autowired
	private TccStockAllocateMapper tccStockAllocateMapper;

	@Autowired
	private TccStockAllocateItemMapper tccStockAllocateItemMapper;

	@Autowired
	private YspTaskService yspTaskService;

	@Autowired
	private StorageMapper storageMapper;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private TccStockControlService tccStockControlService;

	private final Long GRID = 74L;

	/**
	 * 新增
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R add(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("新增传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TccStockAllocate entity = JSON.parseObject(JSON.toJSONString(params), TccStockAllocate.class);
		entity.setStatus(1);//状态
		entity.setEffectStock(0);//审批状态



		//获取制单人信息
		TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setStatus(1).queryFirst();
		if(tsUserChange!=null){
			entity.setCreateChangeId(tsUserChange.getId());//制单人变更信息
		}else {
			return R.error("未查询到制单人信息！");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}

		//新增
		tccStockAllocateMapper.insert(entity);

		YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, entity.getBid(), createUserId);
		}
		//return R.ok(EditDto.closeAndReload());
		return R.ok(AddDto.gotoEdit("/web/storage/tccStockAllocate/toEdit?bid=" + entity.getBid()));
	}


	/**
	 * 修改
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R update(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("修改传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TccStockAllocate entity = JSON.parseObject(JSON.toJSONString(params), TccStockAllocate.class);
		// 验证状态
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst == null) {
			return R.error("审批数据不存在，无法编辑");
		} else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.INIT.value) {
			return R.error("已流转，无法编辑");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}
		tccStockAllocateMapper.update(entity);
		return R.ok();
	}


	//保存子列表信息
	public R saveItem(Map<String, Object> params, TccStockAllocate entity) throws Exception{
		//保存列表信息
		List<Map<String, Object>> subDataList = new ArrayList<>();
		if(params.get("subData")!=null){
			JSONArray subData = JSON.parseArray(params.get("subData").toString());
			CheckByGrid checkByGrid = checkParamsByGrid(subData,GRID,params);
			if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
				return R.error(checkByGrid.getErrMsg());
			}
			subDataList = checkByGrid.getSubDataList();
		}else {
			return R.error("列表信息为空！");
		}

		//先删除详情数据
		storageMapper.deleteTccStockAllocateItemByHandByHandByPbid(entity.getBid());
		//再新增
		for (int i = 0; i < subDataList.size(); i++) {
			Map<String, Object> item = subDataList.get(i);
			TccStockAllocateItem itemInfo = JSON.parseObject(JSON.toJSONString(item), TccStockAllocateItem.class);
			itemInfo.setStatus(1);
			itemInfo.setPbid(entity.getBid());
			//新增
			tccStockAllocateItemMapper.insert(itemInfo);
		}
		return R.ok();
	}


	//删除
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R del(Long id) throws Exception{
		if (id == null) {
			return R.error("ID不能为空");
		}
		TccStockAllocate entity = new TccStockAllocate().setId(id).queryFirst();
		if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("已生效数据无法删除");
		}
		// 验证是否制单人
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
		if (!tsUserChange.getUserId().equals(loginUserId) && !"admin".equals(loginUserId)) {
			return R.error("非制单人，无法删除");
		}
		//删除
		tccStockAllocateMapper.deleteTrue(id);
		//删除列表信息
		storageMapper.deleteTccStockAllocateItemByHandByHandByPbid(entity.getBid());
		//删除流程
		yspTaskService.flowDelete(entity.getBid(), loginUserId);
		return R.ok();
	}



	/**
	 * 流转通过
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowPass(String bid,String loginUserId ) throws Exception {
		//获取单据信息
		TccStockAllocate entity = new TccStockAllocate().setBid(bid).queryFirst();
		if (entity == null) {
			return R.error("该单据不存在,请核实后再操作!");
		}
		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		Flow f = yspTaskService.flowPass(entity.getBid(),loginUserId);

		if (f.getCode() == Flow.Code.FAILED.value) {
			return R.error(f.getMsg());
		} else {
			// 若是制单流转，冻结库存
			if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
				List<TccStockAllocateItem> itemList = new TccStockAllocateItem().setPbid(bid).queryList();
				if(itemList == null || itemList.size()<=0){
					return R.error("该单据列表不存在,请核实后再操作!");
				}
				//冻结
				for(TccStockAllocateItem item:itemList){
					tccStockControlService.frozen(
							item.getStockControlIdByOld(),
							item.getAllocateNum(),
							TccStockSourceEnum.Source.TCC_StockAllocateItem.value,
							entity.getBid(),
							item.getId()
					);
				}
			}
			if (f.getState() == Flow.State.FINISH.value) {
				return flowFinish(entity);
			}
			return R.ok();
		}
	}

	/**
	 * 流转结束
	 */
	public R flowFinish(TccStockAllocate entity) throws Exception {

		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.FINISH.value) {
			return R.error("流程状态有误");
		}

		Date theDate = new Date();
		entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
		entity.setUpdateTime(theDate);

		//获取子表信息
		List<Map<String,Object>> itemList = getItemListByBid(entity.getBid());
		if(itemList == null || itemList.size()<=0){
			return R.error("该单据列表不存在,请核实后再操作!");
		}


		//遍历详情信息
		for (Map<String,Object> item : itemList){
			//获取旧库存信息
			TccStockControl oldStockInfo = new TccStockControl().setId(Long.parseLong(item.get("stockControlIdByOld").toString())).queryFirst();

			//========1、解冻========
			tccStockControlService.thaw(
					Long.parseLong(item.get("stockControlIdByOld").toString()),//旧库存信息
					new BigDecimal(item.get("allocateNum").toString()).intValue(),//调拨数量
					TccStockSourceEnum.Source.TCC_StockAllocateItem.value,
					entity.getBid(),
					Long.parseLong(item.get("id").toString())
			);
			//========2、出库========
			tccStockControlService.outWithRunning(
					Long.parseLong(item.get("stockControlIdByOld").toString()),
					"库存调拨单："+entity.getBid(),
					new BigDecimal(item.get("allocateNum").toString()).intValue(),//调拨数量
					entity.getBid(),
					TccStockSourceEnum.Source.TCC_StockAllocateItem.value,
					entity.getId()
			);

			//========3、入库生成库存 ========
			R res = tccStockControlService.inWithRunning(
					entity.getBid(),
					item.get("chw").toString(),
					item.get("subName").toString(),
					new BigDecimal(item.get("allocateNum").toString()).intValue(),//调拨数量
					item.get("subCode").toString(),
					new BigDecimal(item.get("allocateNum").toString()).intValue(),//调拨数量
					new BigDecimal(item.get("purchasePrice").toString()),
					(new BigDecimal(item.get("purchasePrice").toString())
							.multiply(new BigDecimal(item.get("allocateNum").toString())))
							.setScale(2, BigDecimal.ROUND_HALF_UP),
					BigDecimal.ZERO,
					BigDecimal.ZERO,
					entity.getVgsbm(),
					//theDate,
					oldStockInfo.getDrksj(),//入库时间
					oldStockInfo.getIsParent(),
					entity.getBid(),TccStockSourceEnum.Source.TCC_StockAllocateItem.value,
					"库存调拨单："+entity.getBid(),
					item.get("companyVid")!=null?item.get("companyVid").toString():"",
					entity.getBid(),
					entity.getId()
			);

			TccStockAllocateItem itemEntity = new TccStockAllocateItem();
			long stockControlIdByNew = Long.parseLong(res.get("data").toString());
			itemEntity.setId(Long.parseLong(item.get("id").toString()));
			itemEntity.setStockControlIdByNew(stockControlIdByNew);
			itemEntity.setDrksjByNew(theDate);
			tccStockAllocateItemMapper.update(itemEntity);
		}

		//修改信息
		tccStockAllocateMapper.update(entity);

		return R.ok();

	}



	//流转驳回
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowRefuse(String bid, String reason,String loginUserId) throws Exception{

		R r = yspTaskService.flowRefuse(bid, reason, ShiroUtils.getUserId());

		if (r.getCode() == R.Code.SUCCESS.value) {
			YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
			// 若退回到制单状态，则解冻库存
			if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
				List<TccStockAllocateItem> itemList = new TccStockAllocateItem().setPbid(bid).queryList();
				if(itemList == null || itemList.size()<=0){
					throw new IllegalArgumentException("该单据列表不存在,请核实后再操作!");
					//return R.error("该单据列表不存在,请核实后再操作!");
				}
				//解冻
				for(TccStockAllocateItem item:itemList){
					tccStockControlService.thaw(
							item.getStockControlIdByOld(),
							item.getAllocateNum(),
							TccStockSourceEnum.Source.TCC_StockAllocateItem.value,
							item.getPbid(),
							item.getId()
					);
				}
			}
		}
		return r;
	}



	//流转退回
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowInit(String bid, String reason,String loginUserId) throws Exception{
		R r = yspTaskService.flowInit(bid, reason, ShiroUtils.getUserId());
		if (r.getCode() == R.Code.SUCCESS.value) {
			YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
			// 若退回到制单状态，则解冻库存
			if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
				List<TccStockAllocateItem> itemList = new TccStockAllocateItem().setPbid(bid).queryList();
				if(itemList == null || itemList.size()<=0){
					throw new IllegalArgumentException("该单据列表不存在,请核实后再操作!");
					//return R.error("该单据列表不存在,请核实后再操作!");
				}
				//解冻
				for(TccStockAllocateItem item:itemList){
					tccStockControlService.thaw(
							item.getStockControlIdByOld(),
							item.getAllocateNum(),
							TccStockSourceEnum.Source.TCC_StockAllocateItem.value,
							item.getPbid(),
							item.getId()
					);
				}
			}
		}
		return r;
	}

	//获取母表详情信息
	@Override
	public Map<String,Object> getExtraParam(String bid) throws Exception{
		return new TccStockAllocate()

				.addLeftJoin("YS_ProcInst P ON P.Bid = A.Bid ")
				.addField("FORMAT(P.UpdateTime, 'yyyy-MM-dd HH:mm:ss') AS auditingTime")//审核时间

				.addLeftJoin("THR_OperateCompanyApply C ON C.Vgsbm = A.Vgsbm")
				.addField("C.Vgsjc AS vgsjc")//运营公司简称

				.setBid(bid)
				.queryFirstMap();
	}

	//根据主表bid获取子表信息
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public List<Map<String,Object>> getItemListByBid(String bid) throws Exception {
		//获取子表信息
		return new TccStockAllocateItem()
				//.addField("CASE WHEN A.StockControlIdByNew IS NULL THEN '系统自动赋值' ELSE  CAST(A.StockControlIdByNew AS varchar(50)) END stockControlIdByNewTxt")//库存id
				.addField("CASE WHEN A.StockControlIdByNew IS NULL THEN CAST(A.StockControlIdByOld AS varchar(50)) ELSE  CAST(A.StockControlIdByNew AS varchar(50)) END stockControlIdByNewTxt")//库存id
				.addField("FORMAT(A.DrksjByNew, 'yyyy-MM-dd HH:mm:ss') AS drksjByNewTime")//入库时间

				.addLeftJoin("TP_ProductBasisComponent SB ON SB.Code = A.SubCode")//listing库子件信息

				.addField("SB.SubCodeMerge AS subCodeMerge")//子件合并编码

				.addLeftJoin("TCC_StockControl SC ON SC.Id = A.StockControlIdByOld")//旧库存信息表
				.addField("SC.ProductName AS subName")//子件名称
				.addField("SC.PurchasePrice AS purchasePrice")//采购价

				.addLeftJoin("TCC_Location SD ON SD.Chw = A.Chw")//货位信息表
				.addField("SD.Vhw AS vhw")//货位
				.addLeftJoin("TCC_WarehouseArea SE ON SE.Ckq = SD.Ckq")//库区
				.addField("SE.Vkq AS vkq")//库区
				.addLeftJoin("TCC_Warehouse SF ON SF.Cck = SE.Cck")//仓库
				.addField("SF.Vck AS vck")//仓库

				.addLeftJoin("THR_OperateCompanyApply SG ON SG.Vgsbm = A.VgsbmByOld")
				.addField("SG.Vgsjc AS vgsjcByOld")//运营公司简称

				.addLeftJoin("TB_CompanyInfo SH ON SH.VId = A.CompanyVid")
				.addField("SH.Vname AS vname")//公司名称

				.addField("DATEDIFF(day, A.DrksjByOld, getdate()) kcdaysByOld")//库存天数

				.setPbid(bid)
				//.setOrderby("A.SubCode ASC")
				.queryMap();
	}


	/**
	 * 参数验证
	 */
	public String checkParams(Map<String, Object> params, Long menuId) throws Exception {
		//获取pc字段数据
		List<YsCol> listField = new YsCol()
				.where("A.MenuId = "+menuId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		//验证必填字段的非空；其他字段的长度限制、类型
		String backMsg = checkUtil.checkTableColLengthAndDataType("TCC_StockAllocate",listField,params,ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1);
		//验证税号
		if(checkUtil.isNullByObject(params.get("isManage"))
				&& Integer.parseInt(params.get("isManage").toString())==0
				&& checkUtil.isNullByObject(params.get("vgsSh"))){
			backMsg = "调入运营公司税号为空";
		}

		return backMsg;
	}



	/**
	 * 子表参数验证
	 */
	public CheckByGrid checkParamsByGrid(JSONArray subDataArray, Long gridId,Map<String, Object> params) throws Exception {
		CheckByGrid checkByGrid = new CheckByGrid();
		//获取pc字段数据
		List<YsGridCol> listField = new YsGridCol()
				.setGridId(gridId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		StringBuffer backMsg = new StringBuffer();
		List<Map<String, Object>> subDataList = new ArrayList<>();

		if(subDataArray!=null && subDataArray.size()>0){
			for (int i = 0; i < subDataArray.size(); i++) {
				JSONObject jsonObject = subDataArray.getJSONObject(i);
				Map<String, Object> paramsNewByRecord = new HashMap<>();
				for (String key : jsonObject.keySet()) {
					paramsNewByRecord.put(key, jsonObject.get(key));
				}
				subDataList.add(paramsNewByRecord);
			}
			//验证
			for(int i = 0;i<subDataList.size();i++){
				StringBuffer backMsgByRow = new StringBuffer();
				Map<String, Object> subData = subDataList.get(i);
				//验证必填字段的非空；其他字段的长度限制、类型
				backMsgByRow.append(checkUtil.checkTableColLengthAndDataTypeByGrid(
						"TCC_StockAllocateItem",
						listField,
						subData,
						ysColItem->
								ysColItem.getCode().equals("stockControlIdByOld")
										|| ysColItem.getCode().equals("subCode")
										|| ysColItem.getCode().equals("productNum")
										|| ysColItem.getCode().equals("productNumAll")
										|| ysColItem.getCode().equals("allocateNum")
										|| ysColItem.getCode().equals("chw")
										//|| ysColItem.getCode().equals("companyVid")
										|| ysColItem.getCode().equals("vgsbmByOld")
				));
				if(checkUtil.isNotNullByObject(subData.get("allocateNum")) && !checkUtil.isPositiveInteger(subData.get("allocateNum").toString())){
					backMsgByRow.append("\"调拨数量\"必须是正整数；");
				}

				if(checkUtil.isNotNullByObject(subData.get("allocateNum")) && checkUtil.isNotNullByObject(subData.get("productNum"))){
					if(checkUtil.isPositiveInteger(subData.get("allocateNum").toString())){
						if(new BigDecimal(subData.get("allocateNum").toString()).compareTo(new BigDecimal(subData.get("productNum").toString()))>0){
							backMsgByRow.append("\"调拨数量\" 必须≤ \"商品可用数量\"；");
						}
					}
				}

				//验证税号
				if(params.get("isManage")!=null && Integer.parseInt(params.get("isManage").toString())==0){
					if(checkUtil.isNullByObject(subData.get("vgsShByOld"))){
						backMsgByRow.append("\"公司税号\" 为空；");
					}else {
						if(!subData.get("vgsShByOld").toString().equals(params.get("vgsSh").toString())){
							backMsgByRow.append("公司税号不一致，无法调拨；");
						}
					}
				}

				//验证是否调用同一条库存数据
				if(checkUtil.isNotNullByObject(subData.get("stockControlIdByOld"))){
					boolean isSame = false;
					for(int j = 0;j<subDataList.size();j++){
						Map<String, Object> subDataByCheck = subDataList.get(j);
						if(j!=i && subData.get("stockControlIdByOld").toString().equals(subDataByCheck.get("stockControlIdByOld").toString())){
							isSame = true;
							break;
						}
					}
					if(isSame){
						backMsgByRow.append("不可调用同一条库存信息");
					}
				}
				/*
				//验证运营公司是否一致
				if(checkUtil.isNotNullByObject(subData.get("vgsbmByOld")) && checkUtil.isNotNullByObject(params.get("vgsbm"))){
					if(subData.get("vgsbmByOld").toString().equals(params.get("vgsbm").toString())){
						backMsgByRow.append("调入的运营公司与调出的一致，无需操作；");
					}
				}
				 */

				if(checkUtil.isNotNullByObject(backMsgByRow)){
					backMsg.append("列表第")
							.append((i+1))
							.append("行：")
							.append(backMsgByRow)
							.append("</br>");
				}
			}

		}else{
			backMsg = new StringBuffer("列表信息为空");
		}
		checkByGrid.setErrMsg(backMsg.toString());
		checkByGrid.setSubDataList(subDataList);

		return checkByGrid;
	}






}
